home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / m / fmod.c < prev    next >
C/C++ Source or Header  |  1991-11-21  |  4KB  |  157 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)fmod.c    5.2 (Berkeley) 6/1/90";
  36. #endif /* not lint */
  37.  
  38. /* fmod.c
  39.  *
  40.  * SYNOPSIS
  41.  *
  42.  *    #include <math.h>
  43.  *    double fmod(double x, double y)
  44.  *
  45.  * DESCRIPTION
  46.  *
  47.  *    The fmod function computes the floating-point remainder of x/y.
  48.  *
  49.  * RETURNS
  50.  *
  51.  *    The fmod function returns the value x-i*y, for some integer i
  52.  * such that, if y is nonzero, the result has the same sign as x and
  53.  * magnitude less than the magnitude of y.
  54.  *
  55.  * On a VAX or CCI,
  56.  *
  57.  *    fmod(x,0) traps/faults on floating-point divided-by-zero.
  58.  *
  59.  * On IEEE-754 conforming machines with "isnan()" primitive,
  60.  *
  61.  *    fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned.
  62.  *
  63.  */
  64. #if !defined(vax) && !defined(tahoe)
  65. extern int isnan(),finite();
  66. #endif    /* !defined(vax) && !defined(tahoe) */
  67. extern double frexp(),ldexp(),fabs();
  68.  
  69. #ifdef TEST_FMOD
  70. static double
  71. _fmod(x,y)
  72. #else    /* TEST_FMOD */
  73. double
  74. fmod(x,y)
  75. #endif    /* TEST_FMOD */
  76. double x,y;
  77. {
  78.     int ir,iy;
  79.     double r,w;
  80.  
  81.     if (y == (double)0
  82. #if !defined(vax) && !defined(tahoe)    /* per "fmod" manual entry, SunOS 4.0 */
  83.         || isnan(y) || !finite(x)
  84. #endif    /* !defined(vax) && !defined(tahoe) */
  85.         )
  86.         return (x*y)/(x*y);
  87.  
  88.     r = fabs(x);
  89.     y = fabs(y);
  90.     (void)frexp(y,&iy);
  91.     while (r >= y) {
  92.         (void)frexp(r,&ir);
  93.         w = ldexp(y,ir-iy);
  94.         r -= w <= r ? w : w*(double)0.5;
  95.     }
  96.     return x >= (double)0 ? r : -r;
  97. }
  98.  
  99. #ifdef TEST_FMOD
  100. extern long random();
  101. extern double fmod();
  102.  
  103. #define    NTEST    10000
  104. #define    NCASES    3
  105.  
  106. static int nfail = 0;
  107.  
  108. static void
  109. doit(x,y)
  110. double x,y;
  111. {
  112.     double ro = fmod(x,y),rn = _fmod(x,y);
  113.     if (ro != rn) {
  114.         (void)printf(" x    = 0x%08.8x %08.8x (%24.16e)\n",x,x);
  115.         (void)printf(" y    = 0x%08.8x %08.8x (%24.16e)\n",y,y);
  116.         (void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro);
  117.         (void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn);
  118.         (void)printf("\n");
  119.     }
  120. }
  121.  
  122. main()
  123. {
  124.     register int i,cases;
  125.     double x,y;
  126.  
  127.     srandom(12345);
  128.     for (i = 0; i < NTEST; i++) {
  129.         x = (double)random();
  130.         y = (double)random();
  131.         for (cases = 0; cases < NCASES; cases++) {
  132.             switch (cases) {
  133.             case 0:
  134.                 break;
  135.             case 1:
  136.                 y = (double)1/y; break;
  137.             case 2:
  138.                 x = (double)1/x; break;
  139.             default:
  140.                 abort(); break;
  141.             }
  142.             doit(x,y);
  143.             doit(x,-y);
  144.             doit(-x,y);
  145.             doit(-x,-y);
  146.         }
  147.     }
  148.     if (nfail)
  149.         (void)printf("Number of failures: %d (out of a total of %d)\n",
  150.             nfail,NTEST*NCASES*4);
  151.     else
  152.         (void)printf("No discrepancies were found\n");
  153.     exit(0);
  154. }
  155. #endif    /* TEST_FMOD */
  156.  
  157.